window.addEventListener("orientationchange" in window ? "orientationchange" : "resize", function () {
  var n = window.document.documentElement.clientWidth || 320;
  n > 750 && (n = 750), window.document.documentElement.style.fontSize = n / (750 / 100) + "px";
}, !1);
if (window.document && window.document.addEventListener) {
  window.document.addEventListener("DOMContentLoaded", function () {
    var n = window.document.documentElement.clientWidth || 320;
    n > 750 && (n = 750), window.document.documentElement.style.fontSize = n / (750 / 100) + "px";
  }, !1);
}

declare var wx: wx;
declare var my: my;
declare var upsdk: upsdk;
declare var WeixinJSBridge: WeixinJSBridge;
declare var AMap: AMap;
declare global {
  interface Window {
    [key: string]: any;
  }

  interface wx {
    [key: string]: any;
  }

  interface my {
    [key: string]: any;
  }

  interface upsdk {
    [key: string]: any;
  }

  interface WeixinJSBridge {
    [key: string]: any;
  }

  interface AMap {
    [key: string]: any;
  }
}
declare module "vue/types/vue" {
  interface VueConstructor {
    [key: string]: any;
  }
}

import {
  AnyCallback,
  CheckType,
  IVerifyData,
  FormatType,
  Callback,
  IModal,
  ILocation,
  LocationCallback,
  ChooseImageType,
  ScanCodeType,
  StringCallback,
  IAccount,
  IInputObj,
  IAsynHandler,
  AsynCallback,
} from "../apiType";
import Vue from "vue";
import axios from "axios";
axios.defaults.timeout = 30000;
import { Toast, Dialog, ImagePreview } from "vant";
Vue.use(Toast);
Vue.use(Dialog);

var engine: any = null;
var platformInfo: string = null;
var platformCallbackList: Array<Function> = null;
var storageMap: Map<string, any> = null;
export default {
  refreshObj: null,

  init(logic: any): void {
    engine = this;
    platformCallbackList = [];
    storageMap = new Map();
    if (logic) {
      Object.assign(engine, logic);
      logic.setEngine(engine);
    }
    // 加载平台对应的script
    // if (window.zkpark) {
    //   engine.setCurrentPlatform("zkpark");
    // } else if (window.zkroad) {
    //   engine.setCurrentPlatform("zkroad");
    // } else if (window.location.href.indexOf("/union") > -1) {
    //   engine.loadScript("https://open.95516.com/s/open/js/upsdk.js", (success: boolean, reason: any) => {
    //     engine.getUnionConfig((success: boolean, data: any) => {
    //       if (success) {
    //         upsdk.config({
    //           appId: data.appId,
    //           timestamp: data.timestamp,
    //           nonceStr: data.nonceStr,
    //           signature: data.sign,
    //           jsApiList: [],
    //           debug: data.debug
    //         });
    //         upsdk.ready(() => {
    //           if (upsdk.checkSdkSupport == false) {
    //             engine.setCurrentPlatform("web");
    //             engine.initStorage(logic);
    //           } else {
    //             engine.setCurrentPlatform("union");
    //             engine.initUpkStorage(logic);
    //           }
    //         });
    //         upsdk.error(err => {
    //           engine.setCurrentPlatform("web");
    //           engine.initStorage(logic);
    //         });
    //       } else {
    //         engine.toast("初始化失败，请退出或刷新页面");
    //         upsdk.closeWebApp();
    //       }
    //     });
    //   });
    //   return;
    // } else if (navigator && navigator.userAgent && navigator.userAgent.indexOf("AlipayClient") > -1) {
    //   document.writeln('<script src="https://appx/web-view.min.js"></script>');
    //   engine.setCurrentPlatform("alipay");
    // } else {
      // engine.setCurrentPlatform("web");
      // if (window.WeixinJSBridge && WeixinJSBridge.invoke) {
      //   engine.loadWx();
      // } else {
      //   document.addEventListener("WeixinJSBridgeReady", () => {
      //     engine.loadWx();
      //   }, false);
      // }
    // }
    engine.initStorage(logic);
  },

  loadWx(): void {
    engine.loadScript("https://res.wx.qq.com/open/js/jweixin-1.6.0.js", (success: boolean, reason: any) => {
      if (window.__wxjs_environment == "miniprogram") {
        engine.setCurrentPlatform("wx");
      } else {
        engine.setCurrentPlatform("wechat");
      }
    });
  },

  getCurrentPlatform(): string {
    return platformInfo;
  },

  setCurrentPlatform(info: string): void {
    platformInfo = info;
    if (platformCallbackList.length > 0) {
      for (let i = 0; i < platformCallbackList.length; i++) {
        let callback = platformCallbackList[i];
        if (callback) {
          callback(info);
        }
      }
    }
  },

  registerPlatformCallback(callback: typeof StringCallback): void {
    platformCallbackList.push(callback);
  },

  unRegisterPlatformCallback(callback: typeof StringCallback): void {
    let index = platformCallbackList.indexOf(callback);
    if (index > -1) {
      platformCallbackList.splice(index, 1);
    }
  },

  initStorage(logic: any) {
    storageMap.clear();
    if (sessionStorage && sessionStorage.length > 0) {
      for (let i = 0; i < sessionStorage.length; i++) {
        let key = sessionStorage.key(i);
        let value = sessionStorage.getItem(key);
        storageMap.set(key, value);
      }
    }
    if (logic) {
      logic.checkEngine();
    }
  },

  initUpkStorage(logic: any) {
    upsdk.getAllKeys({
      success(result) {
        if (result && result.code == 0 && result.allKeys) {
          for (let i = 0; i < result.allKeys.length; i++) {
            let key = result.allKeys[i];
            upsdk.queryData({
              key: key,
              success(itemResult) {
                if (itemResult && itemResult.code == 0) {
                  storageMap.set(itemResult.key, itemResult.value);
                }
              }
            });
          }
        }
        if (logic) {
          logic.checkEngine();
        }
      },
      fail() {
        if (logic) {
          logic.checkEngine();
        }
      }
    });
  },

  checkData(data: any, type: string | CheckType): boolean {
    return this.verifyData(data, type).success;
  },

  verifyData(data: any, type: string | CheckType): IVerifyData {
    if (data == undefined || data == null) {
      return {
        success: false,
        data: null
      };
    }
    let value = typeof data == "string" ? data.trim() : data + "";
    if (type) {
      let callback = checkMap.get(type);
      if (callback) {
        return {
          success: callback(value),
          data: value
        };
      }
    }
    return {
      success: true,
      data: value
    };
  },

  formatData(data: any, type: string | FormatType, option?: string): any {
    if (type) {
      let callback = formatMap.get(type);
      if (callback) {
        return callback(data, option);
      }
    }
    return data;
  },

  getUrlSuffixObj(url: string | undefined | null): object | null {
    if (!url) {
      return null;
    }
    let realUrl = decodeURIComponent(url);
    if (!realUrl) {
      return null;
    }
    if (realUrl.endsWith("#/")) {
      realUrl = realUrl.substring(0, realUrl.length - 2);
    }
    let index = realUrl.indexOf("?");
    if (index < 0 || (index + 1) >= realUrl.length) {
      return null;
    }
    let str = realUrl.substring(index + 1, realUrl.length);
    let obj: any = null;
    let array = str.split("&");
    for (let i = 0; i < array.length; i++) {
      let item = array[i];
      let itemIndex = item.indexOf("=");
      if (itemIndex >= 0 && itemIndex < item.length) {
        let itemKey = item.substring(0, itemIndex);
        let itemValue = item.substring(itemIndex + 1, item.length);
        if (!obj) {
          obj = {};
        }
        obj[itemKey] = itemValue;
      }
    }
    return obj;
  },

  getHtmlStyleObj(style: string | undefined | null): object | null {
    if (!style) {
      return null;
    }
    let obj: any = null;
    style.trim().split(";").forEach(item => {
      let subArray = item.split(":");
      if (subArray.length == 2) {
        let key = subArray[0].trim();
        let realkey = "";
        let forceUp = false;
        for (let i = 0; i < key.length; i++) {
          let keyItem = key.charAt(i);
          if (keyItem == "-") {
            forceUp = true;
          } else {
            if (forceUp) {
              forceUp = false;
              realkey += keyItem.toUpperCase();
            } else {
              realkey += keyItem;
            }
          }
        }
        if (realkey.length > 0) {
          if (!obj) {
            obj = {};
          }
          obj[realkey] = subArray[1].trim();
          try {
            let result = JSON.parse(obj[realkey]);
            if (typeof result == "object") {
              obj[realkey] = result;
            }
          } catch (e) { }
        }
      }
    });
    return obj;
  },

  createInputObj(obj?: any): IInputObj {
    return new InputObj(obj);
  },

  createAsynHandler(): IAsynHandler {
    return new AsynHandler();
  },

  log(tag: any, msg?: any): void {
    if (!engine.isDebugMode() || !tag) {
      return;
    }
    if (msg) {
      console.log("zk_" + tag, msg);
    } else {
      console.log("zk_log", tag);
    }
  },

  toast(msg: any): void {
    if (!msg) {
      return;
    }
    Vue.instance.$toast({
      message: typeof msg == "string" ? msg : msg + ""
    });
  },

  showLoading(msg?: string): void {
    Vue.instance.$toast({
      type: "loading",
      duration: 0,
      message: msg
    });
  },

  hideLoading(): void {
    Vue.instance.$toast.clear();
  },

  showModal(param: IModal, callback?: typeof Callback): void {
    let option: any = {
      title: param.title,
      message: param.content,
      showCancelButton: (param.showCancel != undefined && param.showCancel != null) ? param.showCancel : true
    };
    if (param.cancelText) {
      option.cancelButtonText = param.cancelText;
    }
    if (param.confirmText) {
      option.confirmButtonText = param.confirmText;
    } else {
      option.confirmButtonText = "确定";
    }
    Vue.instance.$dialog.alert(option).then(function (data: any) {
      if (callback) {
        callback(true, null);
      }
    }).catch(function (reason: any) {
      if (callback) {
        callback(false, reason);
      }
    });
  },

  getWindowWidth(): number {
    return document.body.clientWidth;
  },

  getWindowHeight(): number {
    return document.body.clientHeight;
  },

  setPageTitle(title: string): void {
    if (platformInfo == "union") {
      upsdk.setNavigationBarTitle({
        title: title
      });
    } else {
      document.title = title;
    }
  },

  enablePullDownRefresh(component: object): void {
    if (engine.refreshObj) {
      engine.refreshObj.enablePullDownRefresh(component);
    }
  },

  disablePullDownRefresh(): void {
    if (engine.refreshObj) {
      engine.refreshObj.disablePullDownRefresh();
    }
  },

  stopPullDownRefresh(): void {
    if (engine.refreshObj) {
      engine.refreshObj.stopPullDownRefresh();
    }
  },

  enableReachBottom(component: object): void {
    if (engine.refreshObj) {
      engine.refreshObj.enableReachBottom(component);
    }
  },

  disableReachBottom(): void {
    if (engine.refreshObj) {
      engine.refreshObj.disableReachBottom();
    }
  },

  setClipboardData(text: string, callback?: typeof Callback): void {
    if (window.clipboardData) {
      try {
        window.clipboardData.setData("Text", text);
        if (callback) {
          callback(true, null);
        }
      } catch (error) {
        if (callback) {
          callback(false, error);
        }
      }
    } else {
      try {
        let oInput = document.createElement("input");
        oInput.value = text + "";
        document.body.appendChild(oInput);
        oInput.select();
        document.execCommand("Copy");
        document.body.removeChild(oInput)
        if (callback) {
          callback(true, null);
        }
      } catch (error) {
        if (callback) {
          callback(false, error);
        }
      }
    }
  },

  getClipboardData(callback: typeof Callback): void {
    if (!callback) {
      return;
    }
    if (window.clipboardData) {
      try {
        let text = window.clipboardData.getData("Text");
        callback(true, text);
      } catch (error) {
        callback(false, error);
      }
    } else {
      callback(false, "getClipboard isn't support");
    }
  },

  jumpPlatformPage(dest: string, param?: object | null, isFinish?: boolean): void {
    if (platformInfo != "zkpark" && platformInfo != "wx" && platformInfo != "alipay") {
      let destPlatform = engine.getDestPlatformSync();
      if (destPlatform == "wx") {
        engine.toast("微信环境加载中，请稍后再试");
      } else {
        engine.toast("跳转失败");
      }
      return;
    }
    if (dest && param) {
      let query = null;
      let realParam: any = param;
      for (let key in realParam) {
        if (!query) {
          query = "?";
        } else {
          query += "&";
        }
        let value = realParam[key];
        if (value && typeof value == "object") {
          try {
            value = JSON.stringify(value);
          } catch (e) { }
        }
        query += key + "=" + value;
      }
      if (query) {
        dest += query;
      }
    }
    try {
      if (platformInfo == "zkpark") {
        if (!dest) {
          window.zkpark.postMessage("zk_finish");
        } else if (isFinish) {
          window.zkpark.postMessage("zk_redirect_" + dest);
        } else {
          window.zkpark.postMessage("zk_navigate_" + dest);
        }
      } else if (platformInfo == "wx") {
        if (!dest) {
          wx.miniProgram.navigateBack();
          wx.miniProgram.postMessage({
            data: "reLogin"
          });
        } else if (isFinish) {
          wx.miniProgram.redirectTo({
            url: dest
          });
        } else {
          wx.miniProgram.navigateTo({
            url: dest
          });
        }
      } else if (platformInfo == "alipay") {
        if (!dest) {
          my.navigateBack();
          my.postMessage({
            data: "reLogin"
          });
        } else if (isFinish) {
          my.redirectTo({
            url: dest
          });
        } else {
          my.navigateTo({
            url: dest
          });
        }
      }
    } catch (error) {
      engine.toast("跳转出错");
    }
  },

  jumpPlatformHomePage(dest: string, param?: object | null): void {
    if (platformInfo != "wx" && platformInfo != "alipay") {
      let destPlatform = engine.getDestPlatformSync();
      if (destPlatform == "wx") {
        engine.toast("微信环境加载中，请稍后再试");
      } else {
        engine.toast("跳转失败");
      }
      return;
    }
    if (dest && param) {
      let query = null;
      let realParam: any = param;
      for (let key in realParam) {
        if (!query) {
          query = "?";
        } else {
          query += "&";
        }
        let value = realParam[key];
        if (value && typeof value == "object") {
          try {
            value = JSON.stringify(value);
          } catch (e) { }
        }
        query += key + "=" + value;
      }
      if (query) {
        dest += query;
      }
    }
    try {
      if (platformInfo == "wx") {
        wx.miniProgram.switchTab({
          url: dest
        });
      } else if (platformInfo == "alipay") {
        my.switchTab({
          url: dest
        })
      }
    } catch (e) {
      engine.toast("跳转出错");
    }
  },

  jumpMiniAppPage(appId: string, isRelease: boolean, dest: string, param?: object | null, isFinish?: boolean): void {
    if (platformInfo != "union") {
      engine.toast("小程序初始化失败");
      return;
    }
    upsdk.openApplet({
      appId: appId,
      toLink: dest,
      param: param ? param : null,
      isFinish: isFinish ? "1" : "0"
    });
  },

  finishPage(backPageNum?: number): void {
    Vue.instance.$router.go(backPageNum ? (backPageNum > 0 ? -backPageNum : backPageNum) : -1);
  },

  jumpPage(dest: string, param?: object | null, isFinish?: boolean): void {
    if (!dest) {
      return;
    }
    let option: any = {
      name: dest
    };
    if (param) {
      option.params = param;
      engine.setAccountCache(dest, param);
    } else {
      engine.setAccountCache(dest);
    }
    if (Vue.instance.$route.name == dest) {
      return;
    }
    if (isFinish) {
      Vue.instance.$router.replace(option);
    } else {
      Vue.instance.$router.push(option);
    }
  },

  getPageParam(): object | null {
    // let param = Vue.instance.$route.params;
    // if (param) {
    //   for (let key in param) {
    //     return param;
    //   }
    // }
    let name = Vue.instance.$route.name;
    return engine.getAccountCache(name);
  },

  getAccountCache(key: string): any {
    if (!key) {
      return null;
    }
    let value = decryptData(storageMap.get(getRealKey(key)));
    if (typeof value == "string") {
      try {
        let result = JSON.parse(value);
        if (typeof result == "object") {
          return result;
        }
      } catch (e) { }
    }
    return value;
  },

  setAccountCache(key: string, value?: any): void {
    if (!key) {
      return;
    }
    let realKey = getRealKey(key);
    if (value != undefined && value != null) {
      if (typeof value != "string") {
        try {
          let result = JSON.stringify(value);
          let realValue = encryptData(result);
          storageMap.set(realKey, realValue);
          if (platformInfo == "union") {
            upsdk.saveData({
              key: realKey,
              value: realValue,
              success(result) {
                if (result && result.code != 0) {
                  storageMap.delete(realKey);
                }
              }
            });
          } else if (sessionStorage) {
            sessionStorage.setItem(realKey, realValue);
          }
          if (engine.setPlatformCache) {
            engine.setPlatformCache(realKey, realValue);
          }
          return;
        } catch (e) { }
      }
      let realValue = encryptData(value);
      storageMap.set(realKey, realValue);
      if (platformInfo == "union") {
        upsdk.saveData({
          key: realKey,
          value: realValue,
          success(result) {
            if (result && result.code != 0) {
              storageMap.delete(realKey);
            }
          }
        });
      } else if (sessionStorage) {
        sessionStorage.setItem(realKey, realValue);
      }
      if (engine.setPlatformCache) {
        engine.setPlatformCache(realKey, realValue);
      }
    } else {
      storageMap.delete(realKey);
      if (platformInfo == "union") {
        upsdk.deleteData({
          key: realKey,
          success() { }
        });
      } else if (sessionStorage) {
        sessionStorage.removeItem(realKey);
      }
      if (engine.removePlatformCache) {
        engine.removePlatformCache(realKey);
      }
    }
  },

  clearAccountCache(): void {
    engine.clearAppCache();
    storageMap.clear();
    if (platformInfo == "union") {
      upsdk.deleteAllKeys({
        success() { }
      });
    } else if (sessionStorage) {
      sessionStorage.clear();
    }
    platformCallbackList.splice(0, platformCallbackList.length);
  },

  requestHttpUrl(url: string, method: string, param: any, header: object, timeout: number): object {
    let option: any = {};
    option.url = url;
    option.method = method;
    if (param && method == "GET") {
      let query = null;
      for (let key in param) {
        let value = param[key];
        if (value && typeof value != "string") {
          try {
            value = JSON.stringify(value);
          } catch (error) { }
        }
        if (!query) {
          query = "?";
        } else {
          query += "&";
        }
        query += key + "=" + value;
      }
      if (query) {
        option.url += query;
      }
    } else {
      option.data = param;
    }
    option.headers = header;
    if (timeout) {
      option.timeout = timeout;
    }
    // axios.interceptors.request.use(function(config) {
    // 	// Do something before request is sent
    // 	return config;
    // }, function(error) {
    // 	// Do something with request error
    // 	return Promise.reject(error);
    // });
    return axios(option);
  },

  requestUploadFile(url: string, fileName: any, filePath: string, formData: FormData, header: object) {
    let option: any = {};
    option.url = url;
    option.name = fileName;
    option.filePath = filePath;
    if (formData) {
      option.formData = formData;
    }
    option.headers = header;
    return axios(option);
  },

  // "OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT"
  requestUrl(isShowLoading: boolean, url: string, method: string, param: object | null, withoutAccount: boolean, timeout: number, linkId: string): Promise<any> {
    return new Promise(function (resolve, reject) {
      if (!url || !method) {
        reject("param error");
        return;
      }
      if (navigator && !navigator.onLine) {
        reject("请连接网络");
        return;
      }
      if (withoutAccount) {
        if (isShowLoading) {
          engine.showLoading();
        }
        engine.requestHttpUrl(url, method, param, engine.getRequestHeader(linkId), timeout).then(function (res: any) {
          engine.requestSuccess(res, isShowLoading, url, param, resolve, reject);
        }).catch(function (reason: any) {
          engine.requestFail(reason, isShowLoading, url, param, reject);
        });
      } else {
        engine.getAccount(function (data: IAccount | null) {
          if (!data) {
            reject("登录失败，无法获取数据");
            return;
          }
          if (isShowLoading) {
            engine.showLoading();
          }
          engine.requestHttpUrl(url, method, param, engine.getRequestHeader(linkId), timeout).then(function (res: any) {
            engine.requestSuccess(res, isShowLoading, url, param, resolve, reject);
          }).catch(function (reason: any) {
            engine.requestFail(reason, isShowLoading, url, param, reject);
          });
        });
      }
    });
  },

  getUrl(isShowLoading: boolean, url: string, param?: object | null, withoutAccount?: boolean, timeout?: number, linkId?: string): Promise<any> {
    return engine.requestUrl(isShowLoading, url, "GET", param, withoutAccount, timeout, linkId);
  },

  postUrl(isShowLoading: boolean, url: string, param?: object | null, withoutAccount?: boolean, timeout?: number, linkId?: string): Promise<any> {
    return engine.requestUrl(isShowLoading, url, "POST", param, withoutAccount, timeout, linkId);
  },

  deleteUrl(isShowLoading: boolean, url: string, param?: object | null, withoutAccount?: boolean, timeout?: number, linkId?: string): Promise<any> {
    return engine.requestUrl(isShowLoading, url, "DELETE", param, withoutAccount, timeout, linkId);
  },

  putUrl(isShowLoading: boolean, url: string, param?: object | null, withoutAccount?: boolean, timeout?: number, linkId?: string): Promise<any> {
    return engine.requestUrl(isShowLoading, url, "PUT", param, withoutAccount, timeout, linkId);
  },

  uploadFile(isShowLoading: boolean, url: string, fileName: string, filePath: string, formData: FormData): Promise<any> {
    if (!fileName && !filePath) {
      return engine.requestUrl(isShowLoading, url, "POST", formData);
    }
    return new Promise(function (resolve, reject) {
      if (!url) {
        reject("param error");
        return;
      }
      if (navigator && !navigator.onLine) {
        reject("请连接网络");
        return;
      }
      if (isShowLoading) {
        engine.showLoading();
      }
      engine.requestUploadFile(url, fileName, filePath, formData, engine.getUploadFileHeader()).then(function (res: any) {
        engine.requestSuccess(res, isShowLoading, url, fileName + "_" + filePath, resolve, reject);
      }).catch(function (reason: any) {
        engine.requestFail(reason, isShowLoading, url, fileName + "_" + filePath, reject);
      });
    });
  },

  loadScript(src: string, callback?: typeof Callback | null): void {
    for (let key in document.body.children) {
      let item = document.body.children[key];
      if (item && item.id == src) {
        if (callback) {
          callback(true, null);
        }
        return;
      }
    }
    let script = document.createElement("script");
    script.id = src;
    script.type = "text/javascript";
    script.src = src;
    script.addEventListener("load", function () {
      if (callback) {
        callback(true, null);
      }
    }, false);
    document.body.append(script);
  },

  requestFail(reason: object, isShowLoading: boolean, url: string, param: object, reject: Function): void {
    if (isShowLoading) {
      engine.hideLoading();
    }
    engine.log("requestUrl:", url);
    engine.log("reason:", reason);
    engine.log("requestParam:", param);
    engine.toast("获取数据出错");
    reject("获取数据出错");
  },

  requestSuccess(res: any, isShowLoading: boolean, url: string, param: object, resolve: Function, reject: Function): void {
    if (isShowLoading) {
      engine.hideLoading();
    }
    if (!res || !res.data) {
      engine.log("requestUrl:", url + "\n res is null");
      engine.log("requestParam:", param);
      engine.toast("获取数据有错");
      reject("获取数据有错");
      return;
    }
    if (typeof res.data == "string") {
      try {
        res.data = JSON.parse(res.data);
      } catch (e) {
        engine.log("requestUrl:", url);
        engine.log("parse:", res.data);
        engine.log("requestParam:", param);
        engine.toast("获取数据解析有错");
        reject("获取数据解析有错");
        return;
      }
    }
    res = res.data;
    if (res.status == 502) {
      engine.toast("服务器升级中");
      reject("服务器升级中");
      return;
    }
    if (res.status != 200) {
      engine.log("requestUrl:", url + "\n status:" + res.status + " statusMsg:" + res.statusMsg);
      engine.log("requestParam:", param);
      reject(res.statusMsg);
      return;
    }
    let resData = res.res;
    if (!resData) {
      engine.log("requestUrl:", url);
      engine.log("res:", res);
      engine.log("requestParam:", param);
      reject("请求发送失败");
      return;
    }
    let code = resData.code;
    if (code == 1000) {
      resolve(resData.data);
    } else if (code == 500 || code == 2607) { // 过期
      engine.log("requestUrl:", url + "\n code:" + code + " codeMsg:" + resData.codeMsg);
      engine.log("requestParam:", param);
      reject("重新登录中");
      engine.handleRequestOverdue();
    } else if (code == 1026) {
      engine.log("requestUrl:", url + "\n code:" + code + " codeMsg:" + resData.codeMsg);
      engine.log("requestParam:", param);
      reject("设备授权已过期");
      engine.handleRequestOverdue();
    } else if (code == 1025) {
      engine.log("requestUrl:", url + "\n code:" + code + " codeMsg:" + resData.codeMsg);
      engine.log("requestParam:", param);
      reject("设备未授权");
      engine.handleRequestOverdue();
    } else {
      engine.log("requestUrl:", url + "\n code:" + code + " codeMsg:" + resData.codeMsg);
      engine.log("requestParam:", param);
      reject(resData.codeMsg);
    }
  },

  getLocation(isShowLoading: boolean, param: ILocation, callback: typeof LocationCallback): void {
    if (!callback) {
      return;
    }
    let hander = new AsynHandler();
    engine.loadScript("https://webapi.amap.com/maps?v=1.4.15&key=" + engine.getMapKey(), hander.register("location"));
    hander.getData(function () {
      if (isShowLoading) {
        engine.showLoading();
      }
      AMap.plugin("AMap.Geolocation", function () {
        let geolocation = new AMap.Geolocation({
          enableHighAccuracy: true,
          timeout: 10000
        })
        let complete = AMap.event.addListener(geolocation, "complete", function (data: any) {
          if (isShowLoading) {
            engine.hideLoading();
          }
          let result: any = {};
          if (data) {
            if (param.type >= 0) {
              if (data.position) {
                result.longitude = data.position.lng;
                result.latitude = data.position.lat;
              }
            }
            if (param.type >= 1) {
              if (data.addressComponent) {
                result.province = data.addressComponent.province;
                result.city = data.addressComponent.city;
                result.district = data.addressComponent.district;
              }
            }
            if (param.type >= 2) {
              result.address = data.formattedAddress;
            }
          }
          AMap.event.removeListener(complete);
          AMap.event.removeListener(error);
          callback(true, result);
        });
        let error = AMap.event.addListener(geolocation, "error", function (reason: any) {
          if (isShowLoading) {
            engine.hideLoading();
          }
          AMap.event.removeListener(complete);
          AMap.event.removeListener(error);
          callback(false, reason);
        });
        geolocation.getCurrentPosition();
      });
    });
  },

  previewImage(urls: Array<string>, startPosition?: number): void {
    let param: any = {};
    param.images = urls;
    if (startPosition != undefined && startPosition != null) {
      param.startPosition = startPosition;
    }
    ImagePreview(param);
  },

  chooseImage(sourceType: string | ChooseImageType, callback: typeof AnyCallback): void {
    if (platformInfo != "union") {
      callback(false, "图库初始化失败");
      return;
    }
    let type: number;
    if (sourceType == "camera") {
      type = 1;
    } else if (sourceType == "original") {
      type = 2;
    } else {
      type = 3;
    }
    let chooseParam: any = {
      maxWidth: "10000",
      maxHeight: "10000",
      sourceType: type,
    };
    chooseParam.success = function (e) {
      callback(true, e.base64);
    };
    chooseParam.fail = function (reason) {
      callback(false, reason);
    }
    upsdk.chooseImage(chooseParam);
  },

  requestPayment(param: any, callback: typeof AnyCallback): void {
    if (platformInfo != "union") {
      callback(false, "支付初始化失败");
      return;
    }
    if (!param) {
      callback(false, "参数错误");
      return;
    }
    param.success = function () {
      callback(true, null);
    }
    param.fail = function (reason) {
      callback(false, reason);
    }
    upsdk.pay(param);
  },

  scanCode(scanType: string | ScanCodeType, callback: typeof AnyCallback): void {
    if (platformInfo != "union") {
      callback(false, "扫码初始化失败");
      return;
    }
    let param: any = {};
    if (scanType == "qrCode" || scanType == "barCode") {
      param.scanType = [scanType];
    } else {
      param.scanType = ["qrCode", "barCode"];
    }
    param.success = function (result) {
      callback(true, result);
    }
    param.fail = function (reason) {
      callback(false, reason);
    }
    upsdk.scanQRCode(param);
  }
}

function getRealKey(param: string): string {
  return "temp_" + param;
}

function encryptData(param: any): string {
  return param;
}

function decryptData(param: any): any {
  return param;
}

var checkMap = new Map();
checkMap.set("integer", function (value: string) { // 是否是正整数
  return /^[0-9]*$/.test(value);
});
checkMap.set("number", function (value: string) { // 是否是正数
  if (value.length < 1) {
    return false;
  }
  let result = Number(value);
  if (isNaN(result)) {
    return false;
  }
  return result >= 0;
});
checkMap.set("integerAll", function (value: string) { // 是否是整数
  return /^[0-9]*$/.test(value) || /^-[0-9]*$/.test(value);
});
checkMap.set("numberAll", function (value: string) { // 是否是数字
  if (value.length < 1) {
    return false;
  }
  return !isNaN(Number(value));
});
checkMap.set("phone", function (value: string) { // 是否是手机号码
  return /^1(3|4|5|6|7|8|9)\d{9}$/.test(value);
});
checkMap.set("carNumber", function (value: string) { // 是否是车牌号码
  return /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$/.test(value) ||
    /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{6}$/.test(value);
});
checkMap.set("idCard", function (value: string) { // 是否是身份证号码
  return /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(value);
});
checkMap.set("email", function (value: string) { // 是否是email
  return /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/.test(value);
});
checkMap.set("http", function (value: string) { // 是否以http开头
  return value.toLocaleLowerCase().startsWith("http://") || value.toLocaleLowerCase().startsWith("https://");
});
checkMap.set("https", function (value: string) { // 是否以https开头
  return value.toLocaleLowerCase().startsWith("https://");
});

var formatMap = new Map();
formatMap.set("time", getFormatTime);
formatMap.set("timeLen", getFormatTimeByLen);
formatMap.set("timeNumber", getTimeNumber);
formatMap.set("date", getDateByType);
formatMap.set("price", toPrice);
formatMap.set("floorPrice", toFloorPrice);

// "yyyy年MM月dd日HH小时mm分钟ss秒"
function getFormatTime(data: any, format: string): string {
  if (!format) {
    return "";
  }
  if (data == undefined || data == null) {
    return "";
  }
  let date = getDate(data);
  if (!date) {
    return "";
  }
  let result = format;
  if (result.indexOf("yyyy") > -1) {
    result = result.replace("yyyy", date.getFullYear() + "");
  }
  if (result.indexOf("MM") > -1) {
    let temp = date.getMonth() + 1;
    result = result.replace("MM", temp < 10 ? "0" + temp : "" + temp);
  }
  if (result.indexOf("dd") > -1) {
    let temp = date.getDate();
    result = result.replace("dd", temp < 10 ? "0" + temp : "" + temp);
  }
  if (result.indexOf("HH") > -1) {
    let temp = date.getHours();
    result = result.replace("HH", temp < 10 ? "0" + temp : "" + temp);
  }
  if (result.indexOf("mm") > -1) {
    let temp = date.getMinutes();
    result = result.replace("mm", temp < 10 ? "0" + temp : "" + temp);
  }
  if (result.indexOf("ss") > -1) {
    let temp = date.getSeconds();
    result = result.replace("ss", temp < 10 ? "0" + temp : "" + temp);
  }
  return result;
}

// "dd天HH小时mm分钟ss秒"
function getFormatTimeByLen(data: any, format: string): string {
  if (!format) {
    return "";
  }
  if (data == undefined || data == null) {
    return "";
  }
  let left = data;
  if (typeof left != "number") {
    left = Number(left);
    if (isNaN(left)) {
      return "";
    }
  }
  if (left < 0) {
    left = -left;
  }
  let result = format;
  if (result.indexOf("dd") > -1) {
    let temp = Math.floor(left / 86400);
    result = result.replace("dd", temp < 10 ? "0" + temp : "" + temp);
    left = left % 86400;
  }
  if (result.indexOf("HH") > -1) {
    let temp = Math.floor(left / 3600);
    result = result.replace("HH", temp < 10 ? "0" + temp : "" + temp);
    left = left % 3600;
  }
  if (result.indexOf("mm") > -1) {
    let temp = Math.floor(left / 60);
    result = result.replace("mm", temp < 10 ? "0" + temp : "" + temp);
    left = left % 60;
  }
  if (result.indexOf("ss") > -1) {
    result = result.replace("mm", left < 10 ? "0" + left : "" + left);
  }
  return result;
}

function getTimeNumber(data: any): number {
  if (data == undefined || data == null) {
    return 0;
  }
  if (data instanceof Date) {
    let value = data.getTime();
    if (isNaN(value)) {
      return 0;
    }
    return value / 1000;
  }
  if (typeof data == "number") {
    return data;
  }
  if (typeof data == "string") {
    try {
      let value = Date.parse(setTimeString(data));
      if (isNaN(value)) {
        return 0;
      }
      return value / 1000;
    } catch (e) { }
  }
  return 0;
}

// "none"或"start"（00时00分00秒）或"end"（23时59分59秒），不传则为"none"
function getDateByType(data: any, type?: string): Date | null {
  let result = getDate(data);
  if (!result) {
    return result;
  }
  if (type == "start") {
    result = getDate(result.toLocaleDateString());
  } else if (type == "end") {
    result = getDate(result.toLocaleDateString());
    if (result) {
      result = getDate(result.getTime() + 24 * 60 * 60 * 1000 - 1);
    }
  }
  return result;
}

function getDate(data: any): Date | null {
  if (data == undefined || data == null) {
    return new Date();
  }
  if (data instanceof Date) {
    if (!isNaN(data.getTime())) {
      return data;
    }
    return null;
  }
  if (typeof data == "number") {
    return new Date(data * 1000);
  }
  if (typeof data == "string") {
    let nData = Number(data);
    if (!isNaN(nData)) {
      return new Date(nData * 1000);
    }
    let date;
    try {
      date = new Date(data);
      if (!isNaN(date.getTime())) {
        return date;
      }
      date = null;
    } catch (e) {
      date = null;
    }
    let value = setTimeString(data);
    try {
      let array = value.split(" ");
      for (let i = 0; i < array.length; i++) {
        let item = array[i];
        if (item.indexOf("/") > -1) {
          date = setDateByDay(item, date);
        } else if (item.indexOf(":") > -1) {
          date = setDateByHour(item, date);
        }
      }
      return date;
    } catch (e) { }
  }
  return null;
}

function setTimeString(str: string): string {
  return str.replace(/-/g, "/").replace(/年/g, "/").replace(/月/g, "/").replace(/日/g, " ")
    .replace(/：/g, ":").replace(/小时/g, ":").replace(/分钟/g, ":").replace(/秒/g, " ")
    .replace(/点/g, ":").replace(/分/g, ":");
}

function setDateByDay(param: string, date: Date | null): Date | null {
  let array: any[] = param.split("/");
  if (array.length == 3) { // 判断成年、月、日
    if (checkNumberArray(array)) {
      let year, day;
      if (array[2] > array[0]) {
        year = array[2];
        day = array[0];
      } else {
        year = array[0];
        day = array[2];
      }
      if (array[1] >= 1 && array[1] <= 12 && day >= 1 && day <= 31) {
        if (!date) {
          date = new Date();
        }
        date.setUTCFullYear(year, array[1] - 1, day);
      }
    }
  } else if (array.length == 2) { // 判断成月和日
    if (checkNumberArray(array)) {
      if (array[0] >= 1 && array[0] <= 12 && array[1] >= 1 && array[1] <= 31) {
        if (!date) {
          date = new Date();
        }
        date.setUTCFullYear(date.getFullYear(), array[0] - 1, array[1]);
      }
    }
  }
  return date;
}

function setDateByHour(param: string, date: Date | null): Date | null {
  let array: any[] = param.split(":");
  if (array.length == 3) { // 判断成小时、分钟、秒
    if (checkNumberArray(array)) {
      if (array[0] >= 0 && array[0] <= 24 && array[1] >= 0 && array[1] <= 59 &&
        array[2] >= 0 && array[2] <= 59) {
        if (!date) {
          date = new Date();
        }
        date.setUTCHours(array[0] - 8, array[1], array[2]);
      }
    }
  } else if (array.length == 2) { // 判断成小时、分钟
    if (checkNumberArray(array)) {
      if (array[0] >= 0 && array[0] <= 24 && array[1] >= 0 && array[1] <= 59) {
        if (!date) {
          date = new Date();
        }
        date.setUTCHours(array[0] - 8, array[1], 0);
      }
    }
  }
  return date;
}

function checkNumberArray(array: any[]): boolean {
  for (let i = 0; i < array.length; i++) {
    let item = Number(array[i]);
    if (isNaN(item)) {
      return false;
    }
    array[i] = item;
  }
  return true;
}

// 精确到小数点的位数，不传则为2
function toPrice(data: any, ratio?: any): number {
  if (data == undefined || data == null) {
    return 0;
  }
  let result = data;
  if (typeof result != "number") {
    result = Number(result);
    if (isNaN(result)) {
      return 0;
    }
  }
  let realRatio = ratio;
  if (realRatio == undefined || realRatio == null) {
    realRatio = 2;
  } else if (typeof realRatio != "number") {
    realRatio = Number(realRatio);
    if (isNaN(realRatio)) {
      realRatio = 2;
    }
  }
  realRatio = Math.pow(10, realRatio);
  return Math.round((result + 0.0000000003) * realRatio) / realRatio;
}

// 精确到小数点的位数，不传则为2
function toFloorPrice(data: any, ratio?: any): number {
  if (data == undefined || data == null) {
    return 0;
  }
  let result = data;
  if (typeof result != "number") {
    result = Number(result);
    if (isNaN(result)) {
      return 0;
    }
  }
  let realRatio = ratio;
  if (realRatio == undefined || realRatio == null) {
    realRatio = 2;
  } else if (typeof realRatio != "number") {
    realRatio = Number(realRatio);
    if (isNaN(realRatio)) {
      realRatio = 2;
    }
  }
  realRatio = Math.pow(10, realRatio);
  return Math.floor((result + 0.0000000003) * realRatio) / realRatio;
}

class InputObj implements IInputObj {
  _obj: any = {};
  _visible = false;

  constructor(obj: any) {
    this.setData(obj);
  }

  setData(obj: any): void {
    if (obj) {
      Object.assign(this, obj);
    }
  }

  getData(): object {
    let obj: any = {};
    Object.getOwnPropertyNames(this).forEach(key => {
      if (key != "__ob__" && key != "_obj" && key != "_visible") {
        let value = this[key];
        if (value != undefined) {
          obj[key] = value;
        }
      }
    });
    return obj;
  }

  clearData(): void {
    Object.getOwnPropertyNames(this).forEach(key => {
      if (key != "__ob__" && key != "_obj" && key != "_visible") {
        this[key] = undefined;
      }
    });
  }

  checkData(key?: string): boolean {
    if (key) {
      let checkCallback = this._obj[key];
      return !checkCallback || checkCallback();
    }
    for (let objKey in this._obj) {
      let checkCallback = this._obj[objKey];
      if (checkCallback && !checkCallback()) {
        return false;
      }
    }
    return true;
  }

  setDialogVisible(visible: boolean): void {
    this._visible = visible;
  }

  isDialogVisible(): boolean {
    return this._visible;
  }

  _register(key: string, checkCallback: Function) {
    this._obj[key] = checkCallback;
  }

  _unRegister(key: string) {
    delete this._obj[key];
  }

  _watch(key: string, callback: Function, formatCallback?: Function): void {
    let value = this[key];
    try {
      Object.defineProperty(this, key, {
        configurable: true,

        get() {
          return value;
        },

        set(val) {
          if (formatCallback) {
            value = formatCallback(val);
          } else {
            value = val;
          }
          callback(value, val);
        }
      });
    } catch (e) {
      console.log("anyfish_watch", e);
    }
    this[key] = value;
  }

  [propName: string]: any;
}

class AsynHandler implements IAsynHandler {
  _data: any = null;
  _listenList: (typeof AsynCallback)[] | null = null;

  // 获取函数：回传key属性对应的值
  register(key: string): typeof AnyCallback {
    if (!this._data) {
      this._data = {};
    }
    if (Object.keys(this._data).indexOf(key) == -1) {
      this._data[key] = undefined;
    }
    let self = this;
    return function (success, data) {
      self._data[key] = (success && data !== undefined) ? data : null;
      if (self.checkData()) {// 处理已提交的申请
        if (self._listenList) {
          self._listenList.forEach(callback => {
            callback(self._data);
          });
          self._listenList = null;
        }
      }
    };
  }

  // 获取：多个key属性对应的值组成的对象
  getData(callback: typeof AsynCallback): void {
    if (!callback) {
      return;
    }
    if (this.checkData()) {
      callback(this._data);
    } else {
      if (!this._listenList) {
        this._listenList = [];
      }
      this._listenList.push(callback);
    }
  }

  // 检查对象是否获取完整
  checkData(): boolean {
    if (!this._data) {
      return false;
    }
    for (let key in this._data) {
      if (this._data[key] === undefined) {
        return false;
      }
    }
    return true;
  }
}